import 'package:flutter/material.dart';
import 'package:lib_draw_text/DrawEmojiUtil.dart';
import 'package:lib_util/ByteUtils.dart';
import 'package:lib_util/CrcUtils.dart';
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'package:ileddemo/code/ble/protocol/base/SizeConverter.dart';
import 'package:ileddemo/code/ble/protocol/base/SourceType.dart';
import 'package:ileddemo/code/ble/protocol/base/RectConverter.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:ileddemo/code/ble/protocol/iledcolor/BleBean.dart';
import 'package:ileddemo/code/ble/protocol/iledcolor/source/text/TextDataUtil.dart';

import '../ColorSourceInterface.dart';
import '../../../base/SourceType.dart';
import '../graffiti/GraffitiSourceBean.dart';
import 'CharBean.dart';

part 'TextSourceBean.g.dart';

///文字类型的素材bean
@JsonSerializable()
class TextSourceBean extends ColorSourceInterface {
  //素材内容
  List<CharBean> content = [];

  //获取完整的字符内容
  String get textContent {
    StringBuffer sb = StringBuffer();
    for (int i = 0; i < content.length; i++) {
      sb.write(content[i].content);
    }
    return sb.toString();
  }

  //文字高度
  int textHeight = 12;

  //是否是多行模式
  bool isMultipleLines = false;

  //旋转角度
  int rotate = 0;

  void setRotate(int rotate) {
    this.rotate = rotate;
    notifyListeners();
  }

  TextSourceBean() {
    sourceType = SourceType.TYPE_TEXT;
  }

  void setCharColor(int index, Color color) {
    content[index].color = color.value;
    notifyListeners();
  }

  @JsonKey(ignore: true)
  Color tmpColor = Colors.white;

  void setTmpColor(Color color) {
    tmpColor = color;
    notifyListeners();
  }

  factory TextSourceBean.fromJson(Map<String, dynamic> json) => _$TextSourceBeanFromJson(json);

  @override
  Map<String, dynamic> toJson() => _$TextSourceBeanToJson(this);

  @override
  Future<List<int>> getSendData(bleBean) async {
    List<int> data = [];
    var l = await cast2GraffitiSourceBeans(bleBean);
    frameCount = l.length;
    //转成要发送的数据
    for (GraffitiSourceBean graffitiSourceBean in l) {
      data.addAll(await graffitiSourceBean.getSendData(bleBean));
    }
    return data;
  }

  Future<List<GraffitiSourceBean>> cast2GraffitiSourceBeans(BleBean bleBean) async {
    //先分割成一屏一屏数据
    var strPathList = await getTextImageList(bleBean);
    //转成image
    List<ui.Image> imageList = await Future.wait(
      strPathList.map((path) async {
        print("文字图片路径: $path");
        return await loadPngFromFile(File(path));
      }),
    );

    //向左和向右移动的是连续的,不需要处理半字问题
    if (effects == 1 || effects == 2) {
      var l = await drawTextAndSplit(imageList, bleBean);
      return l;
    } else {
      //要处理半字问题

      //每一屏要放的文字
      List<List<ui.Image>> frameData = [];
      List<ui.Image> tmpFrame = [];
      int tmpWidthCount = 0;
      frameData.add(tmpFrame);
      for (var image in imageList) {
        if (tmpWidthCount + image.width > bleBean.width) {
          tmpFrame = [];
          frameData.add(tmpFrame);
          tmpWidthCount = 0;
          tmpWidthCount += image.width;
          tmpFrame.add(image);
        } else {
          tmpWidthCount += image.width;
          tmpFrame.add(image);
        }
      }

      //把每一屏的文字,绘制成一整个图片,并居中
      List<GraffitiSourceBean> graffitiSourceBeanList = [];
      for (List<ui.Image> frame in frameData) {
        graffitiSourceBeanList.add(await drawText2Image(frame, bleBean));
      }
      return graffitiSourceBeanList;
    }
  }

  Future<List<GraffitiSourceBean>> drawTextAndSplit(List<ui.Image> frame, BleBean bleBean) async {
    List<GraffitiSourceBean> list = [];
    var recorder = ui.PictureRecorder();
    var canvas = Canvas(recorder);
    Paint paint = Paint();
    double widthIndex = 0;
    for (var image in frame) {
      canvas.drawImage(image, Offset(widthIndex, 0), paint);
      widthIndex += image.width;
    }
    //计算总帧数
    int frameCount = (widthIndex / bleBean.width).ceil();

    Future<GraffitiSourceBean> _cropImage(ui.Image sourceImage, Rect cropRect) async {
      final ui.PictureRecorder recorder = ui.PictureRecorder();
      final Canvas canvas = Canvas(recorder);

      // 使用 drawImageRect 截取部分区域绘制到新图像上
      canvas.drawImageRect(sourceImage, cropRect, Rect.fromLTWH(0, 0, cropRect.width, cropRect.height), Paint());
      var img = await recorder.endRecording().toImage(cropRect.width.toInt(), cropRect.height.toInt());
      // 将 Image 对象转换为字节数据（PNG 格式）
      final ByteData? byteData = await img.toByteData(format: ui.ImageByteFormat.png);
      byteData?.buffer.asUint8List();
      GraffitiSourceBean graffitiSourceBean = GraffitiSourceBean();
      graffitiSourceBean.screenSize = screenSize;
      graffitiSourceBean.imgData = byteData?.buffer.asUint8List();

      return graffitiSourceBean;
    }

    // 结束录制并获取Picture
    var picture = recorder.endRecording();
    // 将整个 Picture 转为 Image
    final ui.Image image = await picture.toImage(bleBean.width * frameCount, bleBean.height);

    for (int i = 0; i < frameCount; i++) {
      var img = await _cropImage(
        image,
        Rect.fromLTWH(bleBean.width * i + 0.0, 0, bleBean.width.toDouble(), bleBean.height.toDouble()),
      );
      list.add(img);
    }

    return list;
  }

  Future<GraffitiSourceBean> drawText2Image(List<ui.Image> frame, BleBean bleBean) async {
    var recorder = ui.PictureRecorder();
    var canvas = Canvas(recorder);
    Paint paint = Paint();
    //计算居中的偏移
    int widthCount = 0;
    for (var image in frame) {
      widthCount += image.width;
    }

    double widthIndex = (bleBean.width - widthCount) ~/ 2 + 0.0;
    for (var image in frame) {
      canvas.drawImage(image, Offset(widthIndex, 0), paint);
      widthIndex += image.width;
    }

    // 结束录制并获取Picture
    var picture = recorder.endRecording();
    var image = await picture.toImage(bleBean.width, bleBean.height);
    // 将 Image 对象转换为字节数据（PNG 格式）
    final ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    GraffitiSourceBean graffitiSourceBean = GraffitiSourceBean();
    graffitiSourceBean.screenSize = screenSize;
    graffitiSourceBean.imgData = byteData?.buffer.asUint8List();

    return graffitiSourceBean;
  }

  Future<ui.Image> loadPngFromFile(File file) async {
    final Uint8List pngData = await file.readAsBytes();
    final ui.Codec codec = await ui.instantiateImageCodec(pngData);
    final ui.FrameInfo frameInfo = await codec.getNextFrame();
    return frameInfo.image;
  }

  ///获取文字素材图片
  Future<List<String>> getTextImageList(BleBean bleBean) async {
    List<String> list = [];
    for (var charBean in content) {
      list.add(
        await TextDataUtil.getTextDataImage(
          charBean.content,
          textHeight,
          rotate,
          charBean.color,
          isSingleColor: bleBean.isSingleColor(),
        ),
      );
    }
    return list;
  }
}
